import os
import re
import logging
from typing import Optional

# 配置日志记录器
logger = logging.getLogger(__name__)

def get_file_extension(filename: str) -> str:
    """
    获取文件扩展名
    
    Args:
        filename: 文件名
        
    Returns:
        扩展名，包括点号，例如 '.jpg'
    """
    _, ext = os.path.splitext(filename)
    return ext.lower()

def get_mime_type(file_extension: str) -> str:
    """
    根据文件扩展名获取MIME类型
    
    Args:
        file_extension: 文件扩展名(包含点号，如 '.jpg')
        
    Returns:
        MIME类型
    """
    # 去掉扩展名前面的点号
    ext = file_extension.lower().lstrip('.')
    
    # 图片格式
    if ext in ['jpg', 'jpeg']:
        return 'image/jpeg'
    elif ext == 'png':
        return 'image/png'
    elif ext == 'gif':
        return 'image/gif'
    elif ext == 'bmp':
        return 'image/bmp'
    elif ext == 'webp':
        return 'image/webp'
    elif ext == 'svg':
        return 'image/svg+xml'
    elif ext == 'tiff':
        return 'image/tiff'
    
    # 视频格式
    elif ext == 'mp4':
        return 'video/mp4'
    elif ext == 'avi':
        return 'video/x-msvideo'
    elif ext == 'mov':
        return 'video/quicktime'
    elif ext == 'wmv':
        return 'video/x-ms-wmv'
    elif ext == 'flv':
        return 'video/x-flv'
    elif ext == 'mkv':
        return 'video/x-matroska'
    elif ext == 'webm':
        return 'video/webm'
    
    # 音频格式
    elif ext == 'mp3':
        return 'audio/mpeg'
    elif ext == 'wav':
        return 'audio/wav'
    elif ext == 'ogg':
        return 'audio/ogg'
    elif ext == 'm4a':
        return 'audio/mp4'
    elif ext == 'flac':
        return 'audio/flac'
    elif ext == 'aac':
        return 'audio/aac'
    
    # 文档格式
    elif ext == 'pdf':
        return 'application/pdf'
    elif ext in ['doc', 'docx']:
        return 'application/msword'
    elif ext in ['xls', 'xlsx']:
        return 'application/vnd.ms-excel'
    elif ext in ['ppt', 'pptx']:
        return 'application/vnd.ms-powerpoint'
    elif ext == 'txt':
        return 'text/plain'
    elif ext == 'csv':
        return 'text/csv'
    elif ext == 'rtf':
        return 'application/rtf'
    
    # 压缩格式
    elif ext == 'zip':
        return 'application/zip'
    elif ext == 'rar':
        return 'application/x-rar-compressed'
    elif ext == '7z':
        return 'application/x-7z-compressed'
    elif ext == 'tar':
        return 'application/x-tar'
    elif ext == 'gz':
        return 'application/gzip'
    
    # 默认MIME类型
    else:
        return 'application/octet-stream'

def detect_file_type(filename: str, mime_type: Optional[str] = None) -> str:
    """
    检测文件类型
    
    Args:
        filename: 文件名
        mime_type: MIME类型(可选)
        
    Returns:
        文件类型(photo/video/audio/document/other)
    """
    extension = get_file_extension(filename)
    
    # 如果没有提供MIME类型，根据扩展名推断
    if not mime_type:
        mime_type = get_mime_type(extension)
    
    # 根据MIME类型分类
    if mime_type.startswith('image/'):
        return 'photo'
    elif mime_type.startswith('video/'):
        return 'video'
    elif mime_type.startswith('audio/'):
        return 'audio'
    elif (mime_type.startswith('application/') and 
          any(x in mime_type for x in ['pdf', 'msword', 'ms-excel', 'ms-powerpoint', 'rtf'])) or \
         (mime_type.startswith('text/')):
        return 'document'
    else:
        # 回退到基于扩展名的检测
        ext = extension.lower().lstrip('.')
        
        # 图片扩展名
        if ext in ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg', 'tiff']:
            return 'photo'
        
        # 视频扩展名
        if ext in ['mp4', 'avi', 'mov', 'wmv', 'flv', 'mkv', 'webm']:
            return 'video'
        
        # 音频扩展名
        if ext in ['mp3', 'wav', 'ogg', 'm4a', 'flac', 'aac']:
            return 'audio'
        
        # 文档扩展名
        if ext in ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'csv', 'rtf']:
            return 'document'
        
        # 默认类型
        return 'other'

def get_file_size_str(size_in_bytes: int) -> str:
    """
    将文件大小(字节)转换为人类可读的字符串
    
    Args:
        size_in_bytes: 文件大小(字节)
        
    Returns:
        格式化的文件大小字符串
    """
    for unit in ['B', 'KB', 'MB', 'GB', 'TB']:
        if size_in_bytes < 1024.0:
            return f"{size_in_bytes:.2f} {unit}"
        size_in_bytes /= 1024.0
    return f"{size_in_bytes:.2f} PB"

def is_valid_filename(filename: str) -> bool:
    """
    检查文件名是否有效
    
    Args:
        filename: 文件名
        
    Returns:
        是否有效
    """
    # 检查文件名是否包含非法字符
    illegal_chars = re.compile(r'[<>:"/\\|?*\x00-\x1f]')
    if illegal_chars.search(filename):
        return False
    
    # 检查文件名是否为空或只包含空格
    if not filename or filename.strip() == '':
        return False
    
    # 检查文件名长度是否合适
    if len(filename) > 255:
        return False
    
    return True

def is_safe_file_type(filename: str, mime_type: Optional[str] = None) -> bool:
    """
    检查文件类型是否安全(非可执行文件)
    
    Args:
        filename: 文件名
        mime_type: MIME类型(可选)
        
    Returns:
        是否安全
    """
    dangerous_extensions = [
        '.exe', '.dll', '.bat', '.cmd', '.msi', '.vbs', '.js',
        '.ps1', '.sh', '.bash', '.php', '.pl', '.py', '.rb'
    ]
    
    extension = get_file_extension(filename)
    
    # 检查扩展名是否在危险列表中
    if extension.lower() in dangerous_extensions:
        return False
    
    # 如果提供了MIME类型，检查是否为可执行类型
    if mime_type and ('application/x-msdownload' in mime_type or 
                      'application/x-executable' in mime_type or
                      'application/x-dosexec' in mime_type):
        return False
    
    return True 